//
//  UIView+Extension.swift
//  SHMechanics
//
//  Created by 张冬 on 2020/10/27.
//  Copyright © 2020 张冬. All rights reserved.
//

import UIKit

extension UIView {
    
    func edgeTo(targetView: UIView) {
        self.topAnchor.constraint(equalTo: targetView.topAnchor).isActive = true
        self.bottomAnchor.constraint(equalTo: targetView.bottomAnchor).isActive = true
        self.leadingAnchor.constraint(equalTo: targetView.leadingAnchor).isActive = true
        self.trailingAnchor.constraint(equalTo: targetView.trailingAnchor).isActive = true
    }
    
    func bottomToSafeBottom(targetView: UIView, constant: CGFloat = 0) -> NSLayoutConstraint {
        if #available(iOS 11.0, *) {
            return self.bottomAnchor.constraint(equalTo: targetView.safeAreaLayoutGuide.bottomAnchor, constant: constant)
        } else {
            return self.bottomAnchor.constraint(equalTo: targetView.bottomAnchor, constant: constant)
        }
    }
    
    func topToSafeTop(targetView: UIView, constant: CGFloat = 0) -> NSLayoutConstraint {
        if #available(iOS 11.0, *) {
            return self.topAnchor.constraint(equalTo: targetView.safeAreaLayoutGuide.topAnchor, constant: constant)
        } else {
            return self.topAnchor.constraint(equalTo: targetView.topAnchor, constant: constant)
        }
    }
    
    @discardableResult
    func withVFL(_ format: String , views: [String: UIView] , options: NSLayoutConstraint.FormatOptions = [] , metrics: [String : Any]? = nil) -> [NSLayoutConstraint] {
        let constraints = NSLayoutConstraint.constraints(withVisualFormat: format, options: options, metrics: metrics, views: views)
        self.addConstraints(constraints)
        return constraints
    }
    
    func addCorner(conrners: UIRectCorner , radius: CGFloat) {
        let maskPath = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: conrners, cornerRadii: CGSize(width: radius, height: radius))
        let maskLayer = CAShapeLayer()
        maskLayer.frame = self.bounds
        maskLayer.path = maskPath.cgPath
        self.layer.mask = maskLayer
    }
    
    /// 添加Alert弹框出动画
    /// - Parameters:
    ///   - duration: 动画时长
    ///   - reversed: 是否执行反向动画, true: 弹出动画, false: 收起动画
    func addExChangeOutAnimation(_ duration: CFTimeInterval, _ reversed: Bool = false) {
        let animation = CAKeyframeAnimation(keyPath: "transform")
        animation.duration = duration
        animation.fillMode = .forwards
        if reversed {
            animation.values = [
                NSValue(caTransform3D: CATransform3DMakeScale(1.0, 1.0, 1.0)),
                NSValue(caTransform3D: CATransform3DMakeScale(0.9, 0.9, 0.9)),
                NSValue(caTransform3D: CATransform3DMakeScale(0.5, 0.5, 1.0))
            ]
        }else {
            animation.values = [
                NSValue(caTransform3D: CATransform3DMakeScale(0.5, 0.5, 1.0)),
                NSValue(caTransform3D: CATransform3DMakeScale(0.9, 0.9, 0.9)),
                NSValue(caTransform3D: CATransform3DMakeScale(1.0, 1.0, 1.0))
            ]
        }
        
        animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
        self.layer.add(animation, forKey: nil)
    }
    
    /// 添加方法动画
    func addScaleBigerAnimation() {
        UIView.animate(withDuration: 0.15, delay: 0,options: [.beginFromCurrentState , .curveEaseInOut]) {
            self.layer.setValue(1.15, forKeyPath: "transform.scale")
        } completion: { (_) in
            UIView.animate(withDuration: 0.15, delay: 0, options: [.beginFromCurrentState , .curveEaseInOut]) {
                self.layer.setValue(0.92, forKeyPath: "transform.scale")
            } completion: { (_) in
                UIView.animate(withDuration: 0.1, delay: 0, options: [.beginFromCurrentState , .curveEaseInOut]) {
                    self.layer.setValue(1.0, forKeyPath: "transform.scale")
                }
            }

        }

    }
    
    /// 找到View的父试图控制器
    func viewController() -> UIViewController? {
        var vc: UIResponder? = self.next
        while vc != nil {
            if vc?.isKind(of: UIViewController.self) == true {
                return vc as? UIViewController
            }
            vc = vc?.next
        }
        return nil
    }
    
    /// 将view转成image
    func screenshotImage() -> UIImage? {
        UIGraphicsBeginImageContextWithOptions(self.size, false, UIScreen.main.scale)
        if let context = UIGraphicsGetCurrentContext() {
            self.layer.render(in: context)
            let image = UIGraphicsGetImageFromCurrentImageContext()
            UIGraphicsEndImageContext()
            return image
        }
        return nil
    }
}

extension Dictionary where Key == String, Value == UIView {
    func addTo(_ view: UIView) {
        self.forEach { (key, value) in
            value.translatesAutoresizingMaskIntoConstraints = false
            view.addSubview(value)
        }
    }
}

enum OscillatoryAnimationType {
    case bigger
    case smaller
}

extension UIView{
    var x : CGFloat {
        get {
            return frame.origin.x
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.origin.x = newValue
            frame = tempFrame
        }
    }
    
    var y : CGFloat {
        get {
            return frame.origin.y
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.origin.y = newValue
            frame = tempFrame
        }
    }
    
    var width : CGFloat {
        get {
            return frame.size.width
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.size.width = newValue
            frame = tempFrame
        }
    }
    
    var height : CGFloat {
        get {
            return frame.size.height
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.size.height = newValue
            frame = tempFrame
        }
    }
    
    var centerX : CGFloat {
        get {
            return center.x
        }
        set {
            var tempCenter : CGPoint = center
            tempCenter.x = newValue
            center = tempCenter
        }
    }
    var centerY : CGFloat {
        get {
            return center.y
        }
        set {
            var tempCenter : CGPoint = center
            tempCenter.y = newValue
            center = tempCenter
        }
    }
    var size : CGSize {
        get {
            return frame.size
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.size = newValue
            frame = tempFrame
        }
    }
    
    var right : CGFloat {
        get {
            return frame.origin.x + frame.size.width
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.origin.x = newValue - frame.size.width
            frame = tempFrame
        }
    }
    
    var bottom : CGFloat {
        get {
            return frame.origin.y + frame.size.height
        }
        set {
            var tempFrame : CGRect = frame
            tempFrame.origin.y = newValue - frame.size.height
            frame = tempFrame
        }
    }
    
    func createGenericShadowLayer(radius: CGFloat) -> CALayer {
        return self.createShadowLayer(shadowColor: UIColor.black.withAlphaComponent(0.1), size: CGSize.init(width: 0, height: 2), opacity: 1, shadowRadius: 2, cornerRadius: radius)
    }
    
    func createShadowLayer(shadowColor: UIColor, size: CGSize, opacity: CGFloat, shadowRadius: CGFloat, cornerRadius: CGFloat) -> CALayer {
        let subLayer = CALayer.init()
        subLayer.frame = self.frame
        subLayer.cornerRadius = cornerRadius
        subLayer.backgroundColor = UIColor.white.cgColor
        subLayer.masksToBounds = false
        subLayer.shadowColor = shadowColor.cgColor
        subLayer.shadowOffset = size
        subLayer.shadowOpacity = Float(opacity)
        subLayer.shadowRadius = shadowRadius
        return subLayer
    }
    
    func createCorner(bounds: CGRect, rectCorner: UIRectCorner, cornerRadius: CGFloat){
        if self.layer.mask != nil {
            return
        }
        if bounds.width == 0 || bounds.height == 0 {
            return
        }
        let maskPath = UIBezierPath.init(roundedRect: bounds, byRoundingCorners: rectCorner, cornerRadii: CGSize.init(width: cornerRadius, height: cornerRadius))
        let shapeLayer = CAShapeLayer.init()
        shapeLayer.path = maskPath.cgPath
        shapeLayer.frame = bounds
        self.layer.mask = shapeLayer
    }
    
    class func showOscillatoryAnimation(layer: CALayer, type: OscillatoryAnimationType) {
        let animationScale1 = (type == .bigger ? 1.15 : 0.5)
        let animationScale2 = (type == .bigger ? 0.92 : 1.15)
        
        UIView.animate(withDuration: 0.15, delay: 0, options: [.beginFromCurrentState,.curveEaseInOut], animations: {
            layer.setValue(animationScale1, forKeyPath: "transform.scale")
        }) { (finished) in
            UIView.animate(withDuration: 0.15, delay: 0, options: [.beginFromCurrentState,.curveEaseInOut], animations: {
                layer.setValue(animationScale2, forKeyPath: "transform.scale")
            }, completion: { (finished) in
                UIView.animate(withDuration: 0.1, delay: 0, options: [.beginFromCurrentState,.curveEaseInOut], animations: {
                    layer.setValue(1.0, forKeyPath: "transform.scale")
                }, completion: nil)
            })
        }
    }
    
    
    /// 使视图面向某个点
    /// - Parameters:
    ///   - target: 目标视图
    ///   - pointCenter: 需要面向的点
    class func viewRotate(target: UIView, targetPoint: CGPoint, pointCenter: CGPoint) {
        let x = (pointCenter.x - targetPoint.x) / UIScreen.main.bounds.size.width
        let y = -(pointCenter.y - targetPoint.y) / UIScreen.main.bounds.size.width
        target.transform = CGAffineTransform.identity
        UIView.animate(withDuration: 0.25) {
            if x == 0 {
                // 在同一垂直方向
                if y >= 0 {
                    target.transform = CGAffineTransform.identity
                }else {
                    target.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
                }
            }else {
                let halfPi = CGFloat.pi * 0.5
                let r = abs(atan(y/x))
                guard r != 0 else {
                    // 在同一水平方向
                    target.transform = CGAffineTransform(rotationAngle:halfPi * (x > 0 ? 1 : -1))
                    return
                }
                if y >= 0, x > 0 {
                    target.transform = CGAffineTransform(rotationAngle:halfPi - r)
                }else if y >= 0, x < 0 {
                    target.transform = CGAffineTransform(rotationAngle:-(halfPi - r))
                }else if y < 0, x > 0 {
                    target.transform = CGAffineTransform(rotationAngle:halfPi + r)
                }else {
                    target.transform = CGAffineTransform(rotationAngle:-(halfPi + r))
                }
            }
        }
    }
}

extension NSLayoutConstraint {
    /// 设置完active后需要拿到对象就用这个方法
    func setIsActive(_ active: Bool) -> Self {
        self.isActive = active
        return self
    }
}

// 链式语法
protocol ChainCode {}

// 为UIView添加链式语法
extension UIView: ChainCode {}

// 链式语法的实现
extension ChainCode {
    public var link: Chainer<Self> {
        return Chainer(self)
    }
}

@dynamicMemberLookup
struct Chainer<Content> {
    
    public let content: Content
    
    public var end: Content {
        return self.content
    }
    
    init(_ content: Content) {
        self.content = content
    }
    
    subscript<Value>(dynamicMember keyPath: WritableKeyPath<Content, Value>) -> ((Value) -> Chainer<Content>) {
        var subject = self.content
        return { value in
            subject[keyPath: keyPath] = value
            return Chainer(subject)
        }
    }
}


